// 增强通知服务 - 提供高级通知功能和用户体验优化

// 基础通知服务接口（简化版，避免循环依赖）
interface BaseNotificationService {
  requestPermission(): Promise<NotificationPermission>;
}

export interface EnhancedNotificationOptions {
  title: string;
  body?: string;
  icon?: string;
  badge?: string;
  tag?: string;
  data?: any;
  actions?: NotificationAction[];
  requireInteraction?: boolean;
  silent?: boolean;
  vibrate?: number[];
  timestamp?: number;
  renotify?: boolean;
  image?: string;
  // 新增的增强选项
  priority?: 'low' | 'normal' | 'high' | 'urgent';
  category?: 'task' | 'reminder' | 'deadline' | 'achievement' | 'system';
  autoClose?: boolean;
  autoCloseDelay?: number;
  sound?: string | boolean;
  customStyle?: NotificationStyle;
  actionCallbacks?: Record<string, () => void>;
  onShow?: () => void;
  onClose?: () => void;
  onClick?: () => void;
  onError?: (error: Error) => void;
}

export interface NotificationStyle {
  backgroundColor?: string;
  textColor?: string;
  borderColor?: string;
  iconStyle?: 'default' | 'rounded' | 'circle';
}

export interface NotificationAction {
  action: string;
  title: string;
  icon?: string;
}

export interface NotificationTemplate {
  id: string;
  name: string;
  title: string;
  body: string;
  icon?: string;
  actions?: NotificationAction[];
  priority: 'low' | 'normal' | 'high' | 'urgent';
  category: string;
}

export interface NotificationStats {
  totalSent: number;
  totalClicked: number;
  totalDismissed: number;
  clickRate: number;
  categoryCounts: Record<string, number>;
  recentNotifications: Array<{
    id: string;
    title: string;
    timestamp: number;
    clicked: boolean;
    category: string;
  }>;
}

export class EnhancedNotificationService {
  private static instance: EnhancedNotificationService;
  private baseService: BaseNotificationService;

  private activeNotifications: Map<string, Notification> = new Map();
  private templates: Map<string, NotificationTemplate> = new Map();
  private stats: NotificationStats;
  private soundCache: Map<string, HTMLAudioElement> = new Map();

  private constructor() {
    this.baseService = {
      requestPermission: async () => {
        if (!('Notification' in window)) {
          return 'denied' as NotificationPermission;
        }
        if (Notification.permission !== 'denied') {
          return await Notification.requestPermission();
        }
        return Notification.permission;
      }
    };
    this.stats = this.loadStats();
    this.initializeTemplates();
    this.initializeSounds();
  }

  public static getInstance(): EnhancedNotificationService {
    if (!EnhancedNotificationService.instance) {
      EnhancedNotificationService.instance = new EnhancedNotificationService();
    }
    return EnhancedNotificationService.instance;
  }

  // 初始化预定义模板
  private initializeTemplates(): void {
    const templates: NotificationTemplate[] = [
      {
        id: 'task-reminder',
        name: '任务提醒',
        title: '📋 任务提醒',
        body: '您有一个任务即将到期',
        icon: '/icon-192x192.png', // 使用现有的PWA图标
        priority: 'normal',
        category: 'reminder',
        actions: [
          { action: 'view', title: '查看任务' },
          { action: 'snooze', title: '稍后提醒' },
          { action: 'complete', title: '标记完成' }
        ]
      },
      {
        id: 'deadline-urgent',
        name: '紧急截止提醒',
        title: '⚠️ 紧急提醒',
        body: '任务即将过期！',
        icon: '/icon-192x192.png',
        priority: 'urgent',
        category: 'deadline',
        actions: [
          { action: 'view', title: '立即处理' },
          { action: 'extend', title: '延期' }
        ]
      },
      {
        id: 'achievement',
        name: '成就解锁',
        title: '🎉 恭喜！',
        body: '您获得了新成就',
        icon: '/icon-192x192.png',
        priority: 'high',
        category: 'achievement',
        actions: [
          { action: 'view', title: '查看详情' }
        ]
      },
      {
        id: 'daily-summary',
        name: '每日总结',
        title: '📊 今日任务总结',
        body: '查看您今天的完成情况',
        icon: '/icon-192x192.png',
        priority: 'low',
        category: 'system'
      }
    ];

    templates.forEach(template => {
      this.templates.set(template.id, template);
    });
  }

  // 初始化音效
  private initializeSounds(): void {
    const sounds = [
      { name: 'default', url: '/sounds/notification.mp3' },
      { name: 'urgent', url: '/sounds/urgent.mp3' },
      { name: 'success', url: '/sounds/success.mp3' },
      { name: 'reminder', url: '/sounds/reminder.mp3' }
    ];

    sounds.forEach(sound => {
      try {
        const audio = new Audio(sound.url);
        audio.preload = 'none'; // 改为按需加载
        
        // 检查音频文件是否存在
        audio.addEventListener('error', () => {
          console.warn(`音频文件 ${sound.url} 不存在，将使用系统默认音效`);
        });
        
        this.soundCache.set(sound.name, audio);
      } catch (error) {
        console.warn(`初始化音频 ${sound.name} 失败:`, error);
      }
    });
  }

  // 显示增强通知
  public async showEnhancedNotification(options: EnhancedNotificationOptions): Promise<string | null> {
    try {
      // 检查权限
      const permission = await this.baseService.requestPermission();
      if (permission !== 'granted') {
        console.warn('通知权限被拒绝');
        return null;
      }

      // 生成通知ID
      const notificationId = options.tag || `notification-${Date.now()}`;

      // 应用优先级样式
      const enhancedOptions = this.applyPriorityStyles(options);

      // 播放声音
      if (options.sound !== false) {
        await this.playNotificationSound(options.sound, options.priority);
      }

      // 创建通知
      const notification = await this.createEnhancedNotification(enhancedOptions);
      if (!notification) return null;

      // 存储活跃通知
      this.activeNotifications.set(notificationId, notification);

      // 设置事件监听器
      this.setupNotificationEvents(notification, options, notificationId);

      // 自动关闭处理
      if (options.autoClose !== false) {
        const delay = options.autoCloseDelay || this.getAutoCloseDelay(options.priority);
        setTimeout(() => {
          this.closeNotification(notificationId);
        }, delay);
      }

      // 更新统计
      this.updateStats('sent', (options.category as string) || 'unknown');

      // 触发显示回调
      options.onShow?.();

      return notificationId;
    } catch (error) {
      console.error('显示增强通知失败:', error);
      options.onError?.(error as Error);
      return null;
    }
  }

  // 使用模板显示通知
  public async showTemplateNotification(
    templateId: string, 
    data: Record<string, any> = {},
    overrides: Partial<EnhancedNotificationOptions> = {}
  ): Promise<string | null> {
    const template = this.templates.get(templateId);
    if (!template) {
      console.error(`模板 ${templateId} 不存在`);
      return null;
    }

    // 替换模板变量
    const title = this.replaceTemplateVariables(template.title, data);
    const body = this.replaceTemplateVariables(template.body, data);

    const options: EnhancedNotificationOptions = {
      title,
      body,
      icon: template.icon,
      actions: template.actions,
              priority: template.priority,
        category: template.category as any,
      tag: `template-${templateId}-${Date.now()}`,
      ...overrides
    };

    return await this.showEnhancedNotification(options);
  }

  // 批量通知
  public async showBatchNotifications(
    notifications: EnhancedNotificationOptions[],
    options: {
      delay?: number;
      maxConcurrent?: number;
      groupByCategory?: boolean;
    } = {}
  ): Promise<string[]> {
    const { delay = 1000, maxConcurrent = 3, groupByCategory = false } = options;
    const results: string[] = [];

    if (groupByCategory) {
      // 按类别分组
      const grouped = notifications.reduce((acc, notification) => {
        const category = (notification.category as string) || 'default';
        if (!acc[category]) acc[category] = [];
        acc[category].push(notification);
        return acc;
      }, {} as Record<string, EnhancedNotificationOptions[]>);

      // 为每个类别创建汇总通知
      for (const [category, items] of Object.entries(grouped)) {
        if (items.length > 1) {
          const summaryId = await this.showEnhancedNotification({
            title: `${this.getCategoryDisplayName(category)} (${items.length}条)`,
            body: items.map(item => item.title).join(', '),
            category: category as any,
            priority: 'normal',
            tag: `batch-${category}-${Date.now()}`,
            actions: [
              { action: 'view-all', title: '查看全部' }
            ]
          });
          if (summaryId) results.push(summaryId);
        } else {
          const id = await this.showEnhancedNotification(items[0]);
          if (id) results.push(id);
        }
      }
    } else {
      // 限制并发数量
      for (let i = 0; i < notifications.length; i += maxConcurrent) {
        const batch = notifications.slice(i, i + maxConcurrent);
        const batchPromises = batch.map(notification => this.showEnhancedNotification(notification));
        const batchResults = await Promise.all(batchPromises);
        
        results.push(...batchResults.filter(id => id !== null) as string[]);
        
        // 延迟下一批
        if (i + maxConcurrent < notifications.length) {
          await new Promise(resolve => setTimeout(resolve, delay));
        }
      }
    }

    return results;
  }

  // 智能提醒时间计算
  public calculateSmartReminderTime(
    dueDate: Date,
    taskComplexity: 'simple' | 'medium' | 'complex' = 'medium',
    userPreferences: {
      workingHours?: { start: number; end: number };
      preferredReminderTimes?: number[]; // 分钟数组
      timezone?: string;
    } = {}
  ): Date[] {
    const now = new Date();
    const timeDiff = dueDate.getTime() - now.getTime();
    const hoursUntilDue = timeDiff / (1000 * 60 * 60);

    // 基于任务复杂度的默认提醒时间
    const complexityReminders = {
      simple: [30, 60], // 30分钟, 1小时
      medium: [60, 240, 1440], // 1小时, 4小时, 1天
      complex: [240, 1440, 4320] // 4小时, 1天, 3天
    };

    let reminderMinutes = userPreferences.preferredReminderTimes || complexityReminders[taskComplexity];

    // 过滤已过期的提醒时间
    reminderMinutes = reminderMinutes.filter(minutes => minutes < hoursUntilDue * 60);

    // 转换为具体时间
    const reminderTimes = reminderMinutes.map(minutes => {
      const reminderTime = new Date(dueDate.getTime() - (minutes * 60 * 1000));
      
      // 调整到工作时间
      if (userPreferences.workingHours) {
        const { start, end } = userPreferences.workingHours;
        const hour = reminderTime.getHours();
        
        if (hour < start) {
          reminderTime.setHours(start, 0, 0, 0);
        } else if (hour >= end) {
          // 推迟到第二天的工作开始时间
          reminderTime.setDate(reminderTime.getDate() + 1);
          reminderTime.setHours(start, 0, 0, 0);
        }
      }
      
      return reminderTime;
    });

    return reminderTimes.filter(time => time > now);
  }

  // 关闭通知
  public closeNotification(notificationId: string): void {
    const notification = this.activeNotifications.get(notificationId);
    if (notification) {
      notification.close();
      this.activeNotifications.delete(notificationId);
    }
  }

  // 关闭所有通知
  public closeAllNotifications(): void {
    this.activeNotifications.forEach((notification) => {
      notification.close();
    });
    this.activeNotifications.clear();
  }

  // 获取通知统计
  public getNotificationStats(): NotificationStats {
    return { ...this.stats };
  }

  // 清除通知统计
  public clearStats(): void {
    this.stats = {
      totalSent: 0,
      totalClicked: 0,
      totalDismissed: 0,
      clickRate: 0,
      categoryCounts: {},
      recentNotifications: []
    };
    this.saveStats();
  }

  // 私有方法

  private applyPriorityStyles(options: EnhancedNotificationOptions): EnhancedNotificationOptions {
    const priorityConfig = {
      low: {
        vibrate: [100],
        requireInteraction: false,
        autoCloseDelay: 3000
      },
      normal: {
        vibrate: [200, 100, 200],
        requireInteraction: false,
        autoCloseDelay: 5000
      },
      high: {
        vibrate: [200, 100, 200, 100, 200],
        requireInteraction: true,
        autoCloseDelay: 8000
      },
      urgent: {
        vibrate: [300, 100, 300, 100, 300, 100, 300],
        requireInteraction: true,
        autoCloseDelay: 0, // 不自动关闭
        renotify: true
      }
    };

    const config = priorityConfig[options.priority || 'normal'];
    
    return {
      ...options,
      vibrate: options.vibrate || config.vibrate,
      requireInteraction: options.requireInteraction ?? config.requireInteraction,
      autoCloseDelay: options.autoCloseDelay || config.autoCloseDelay
    };
  }

  private async createEnhancedNotification(options: EnhancedNotificationOptions): Promise<Notification | null> {
    const notificationOptions: any = {
      body: options.body,
      icon: options.icon || '/icon-192x192.png',
      badge: options.badge || '/icon-192x192.png',
      tag: options.tag,
      data: options.data,
      requireInteraction: options.requireInteraction,
      silent: options.silent,
      vibrate: options.vibrate,
      timestamp: options.timestamp,
      image: options.image
    };

    try {
      return new Notification(options.title, notificationOptions);
    } catch (error) {
      console.error('创建通知失败:', error);
      return null;
    }
  }

  private setupNotificationEvents(
    notification: Notification,
    options: EnhancedNotificationOptions,
    notificationId: string
  ): void {
    notification.onclick = (event) => {
      event.preventDefault();
      this.updateStats('clicked', options.category || 'unknown');
      options.onClick?.();
      
      // 处理默认点击行为
      if (options.data?.taskId) {
        window.focus();
        window.location.hash = `/task/${options.data.taskId}`;
      }
      
      this.closeNotification(notificationId);
    };

    notification.onclose = () => {
      this.updateStats('dismissed', options.category || 'unknown');
      options.onClose?.();
      this.activeNotifications.delete(notificationId);
    };

    notification.onerror = (error) => {
      console.error('通知错误:', error);
      options.onError?.(error as any);
    };

    // 处理动作按钮
    if (options.actionCallbacks) {
      // 注意：Web API的通知动作需要通过Service Worker处理
      // 这里只是示例，实际需要在Service Worker中实现
      Object.entries(options.actionCallbacks).forEach(([action, callback]) => {
        // 通过postMessage与Service Worker通信
        navigator.serviceWorker?.ready.then(registration => {
          registration.active?.postMessage({
            type: 'NOTIFICATION_ACTION',
            notificationId,
            action,
            callback: callback.toString()
          });
        });
      });
    }
  }

  private async playNotificationSound(
    sound: string | boolean | undefined,
    priority?: string
  ): Promise<void> {
    if (sound === false) return;

    let soundName = 'default';
    if (typeof sound === 'string') {
      soundName = sound;
    } else if (priority === 'urgent') {
      soundName = 'urgent';
    }

    const audio = this.soundCache.get(soundName);
    if (audio) {
      try {
        // 检查音频是否可以播放
        if (audio.readyState === HTMLMediaElement.HAVE_NOTHING) {
          // 如果音频未加载，尝试加载
          audio.load();
        }
        
        audio.currentTime = 0;
        await audio.play();
      } catch (error) {
        console.warn('播放通知音效失败:', error);
        // 降级：使用Web Audio API创建简单的提示音
        this.playFallbackSound(priority);
      }
    } else {
      // 如果没有音频文件，使用降级方案
      this.playFallbackSound(priority);
    }
  }

  // 降级音效方案
  private playFallbackSound(priority?: string): void {
    try {
      // 使用Web Audio API创建简单的提示音
      const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
      const oscillator = audioContext.createOscillator();
      const gainNode = audioContext.createGain();

      oscillator.connect(gainNode);
      gainNode.connect(audioContext.destination);

      // 根据优先级设置不同的音调
      if (priority === 'urgent') {
        oscillator.frequency.setValueAtTime(880, audioContext.currentTime); // A5
        oscillator.frequency.setValueAtTime(1108, audioContext.currentTime + 0.1); // C#6
      } else {
        oscillator.frequency.setValueAtTime(523, audioContext.currentTime); // C5
      }

      gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
      gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2);

      oscillator.start(audioContext.currentTime);
      oscillator.stop(audioContext.currentTime + 0.2);
    } catch (error) {
      console.warn('降级音效播放失败:', error);
      // 最后的降级：什么都不做，依赖浏览器的默认通知音效
    }
  }

  private getAutoCloseDelay(priority?: string): number {
    const delays = {
      low: 3000,
      normal: 5000,
      high: 8000,
      urgent: 0 // 不自动关闭
    };
    return delays[priority as keyof typeof delays] || delays.normal;
  }

  private replaceTemplateVariables(template: string, data: Record<string, any>): string {
    return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
      return data[key] !== undefined ? String(data[key]) : match;
    });
  }

  private getCategoryDisplayName(category: string): string {
    const names = {
      task: '任务',
      reminder: '提醒',
      deadline: '截止日期',
      achievement: '成就',
      system: '系统消息'
    };
    return names[category as keyof typeof names] || category;
  }

  private updateStats(action: 'sent' | 'clicked' | 'dismissed', category: string): void {
    if (action === 'sent') {
      this.stats.totalSent++;
      this.stats.categoryCounts[category] = (this.stats.categoryCounts[category] || 0) + 1;
      
      this.stats.recentNotifications.unshift({
        id: `notif-${Date.now()}`,
        title: `通知 - ${category}`,
        timestamp: Date.now(),
        clicked: false,
        category
      });
      
      // 保持最近通知列表不超过100条
      this.stats.recentNotifications = this.stats.recentNotifications.slice(0, 100);
    } else if (action === 'clicked') {
      this.stats.totalClicked++;
      
      // 更新最近通知的点击状态
      const recent = this.stats.recentNotifications[0];
      if (recent) {
        recent.clicked = true;
      }
    } else if (action === 'dismissed') {
      this.stats.totalDismissed++;
    }

    // 计算点击率
    this.stats.clickRate = this.stats.totalSent > 0 
      ? (this.stats.totalClicked / this.stats.totalSent) * 100 
      : 0;

    this.saveStats();
  }

  private loadStats(): NotificationStats {
    try {
      const saved = localStorage.getItem('enhanced-notification-stats');
      if (saved) {
        return JSON.parse(saved);
      }
    } catch (error) {
      console.error('加载通知统计失败:', error);
    }

    return {
      totalSent: 0,
      totalClicked: 0,
      totalDismissed: 0,
      clickRate: 0,
      categoryCounts: {},
      recentNotifications: []
    };
  }

  private saveStats(): void {
    try {
      localStorage.setItem('enhanced-notification-stats', JSON.stringify(this.stats));
    } catch (error) {
      console.error('保存通知统计失败:', error);
    }
  }
}

export default EnhancedNotificationService;
